home *** CD-ROM | disk | FTP | other *** search
/ Amiga Packmags / Source, The - Issue 5 (1993)(Epsilon)[WB].zip / Source, The - Issue 5 (1993)(Epsilon)[WB].adf / Source / Vectors / Rendering / Ellipse.lha / ellipse.code < prev   
Internet Message Format  |  1989-10-24  |  8KB

  1. From albanycs!leah:rsb584 Sat Jan  9 13:58:34 1988
  2. Received: by albanycs.albany.edu (5.54/4.8)
  3.     id AA07219; Sat, 9 Jan 88 13:18:01 EST
  4. Date: Sat, 9 Jan 88 13:17:58 EST
  5. From: albanycs!leah:rsb584 ( Raymond S Brand)
  6. Received: by leah.Albany.EDU (5.58/1.1)
  7.     id AA12515; Sat, 9 Jan 88 13:17:58 EST
  8. Message-Id: <8801091817.AA12515@leah.Albany.EDU>
  9. To: albanycs:beowulf!rsbx
  10.  
  11. >From jackm@devvax.JPL.NASA.GOV Fri Jan  8 11:21:09 1988
  12. Path: leah!uwmcsd1!bbn!oberon!cit-vax!elroy!devvax!jackm
  13. From: jackm@devvax.JPL.NASA.GOV (Jack Morrison)
  14. Newsgroups: comp.graphics
  15. Subject: Re: circles with non-unity aspect ratio (Ellipses! LONG, w/code)
  16. Keywords: circles, ellipses, algorithms
  17. Message-ID: <971@devvax.JPL.NASA.GOV>
  18. Date: 8 Jan 88 16:21:09 GMT
  19. Reply-To: jackm@devvax.JPL.NASA.GOV (Jack Morrison)
  20. Organization: Jet Propulsion Laboratory, Pasadena, CA.
  21. Lines: 232
  22.  
  23. A few requests for ellipses have prompted me to include this code. It
  24. draws ellipses (including circles, of course) of varying line width
  25. on a SUN bitmap display. (It's part of a paint-type program). I don't
  26. know how this compares to the earlier posting of an ellipse algorithm,
  27. but it's fairly fast.
  28.  
  29. Enjoy or flame....
  30.  
  31. =====================================================================
  32.  
  33. /***********************************************/
  34. /* gred_ellipse.c - draw ellipses        *
  35. /* algorithm from IEEE CG&A Sept 1984 p.24     *
  36. /***********************************************/
  37. #include <stdio.h>
  38. #include <sunwindow/window_hs.h>
  39.  
  40. gred_ellipse (cx, cy, radius_x, radius_y, line_width, pw, pattern_pr)
  41. int               cx, cy;
  42. int               radius_x, radius_y;
  43. int            line_width;
  44. struct pixwin         *pw;
  45. struct pixrect         *pattern_pr;
  46. {
  47.     struct pixrect     *pr;
  48.     int            inner_radius_x;
  49.     int            inner_radius_y;
  50.     int            outer_radius_x;
  51.     int            outer_radius_y;
  52.  
  53. /*******************************************************************/
  54. /* Calculate the inner, outer radiuses of the ellipse              */
  55. /*******************************************************************/
  56.     /* if one pixel wide, radiuses are same */
  57.     if (line_width < 2)
  58.     {
  59.     inner_radius_x = outer_radius_x = radius_x;
  60.     inner_radius_y = outer_radius_y = radius_y;
  61.     }
  62.     else
  63.     {
  64.     outer_radius_x = radius_x + (line_width >> 1);
  65.     outer_radius_y = radius_y + (line_width >> 1);
  66.     inner_radius_x = outer_radius_x - line_width + 1;
  67.     inner_radius_y = outer_radius_y - line_width + 1;
  68.     }
  69.  
  70. /*******************************************************************/
  71. /* Create a pixrect to build the ellipse in.                       */
  72. /*******************************************************************/
  73.     pr = mem_create ((outer_radius_x << 1) + 1, (outer_radius_y << 1) + 1, 1);
  74.     /* now clear it */
  75.     pr_rop (pr,    0, 0, pr -> pr_size.x, pr -> pr_size.y,
  76.         PIX_CLR, (struct pixrect *) 0, 0, 0);
  77.  
  78. /*******************************************************************/
  79. /* If the inner_radius > 0 then outline the inner edge.            */
  80. /* Then if the outer radius of the ellipse is > than the inner     */
  81. /* radius, call the fill ellipse routine with the outer radius.    */
  82. /*******************************************************************/
  83.     if ((inner_radius_x > 0)
  84.             && (inner_radius_y > 0))
  85.         outline_ellipse (pr, outer_radius_x, outer_radius_y, 
  86.         inner_radius_x, inner_radius_y);
  87.  
  88.     if (line_width >=  2)
  89.     fill_ellipse(pr, outer_radius_x, outer_radius_y, 
  90.         outer_radius_x, outer_radius_y);
  91.     
  92. /*******************************************************************/
  93. /* Now write the ellipse out to the window.                        */
  94. /*******************************************************************/
  95.     inner_radius_x = inner_radius_y = 0;    /* normal source offset */
  96.     if ((cx -= outer_radius_x) < 0)    /* ellipse extends beyond left edge? */
  97.     {
  98.     inner_radius_x = -cx;
  99.     cx = 0;
  100.     }
  101.     if ((cy -= outer_radius_y) < 0)    /* above top edge? */
  102.     {
  103.         inner_radius_y = -cy;
  104.     cy = 0;
  105.     }
  106.  
  107.     if (pattern_pr == NULL)
  108.         pw_write (pw, cx, cy, pr->pr_size.x-inner_radius_x, pr->pr_size.y-inner_radius_y,
  109.         PIX_SRC ^ PIX_DST, pr, inner_radius_x, inner_radius_y);
  110.     else
  111.     pw_stencil (pw, cx, cy, pr -> pr_size.x, pr -> pr_size.y, 
  112.         PIX_SRC, pr, inner_radius_x, inner_radius_y, pattern_pr, 0, 0);
  113.  
  114.     pr_destroy (pr);
  115. }
  116.  
  117.  
  118. /* draw ellipse incrementally */
  119. static outline_ellipse (pr, center_x, center_y, rx, ry)
  120. struct pixrect *pr;
  121. int    center_x, center_y;
  122. int    rx, ry;
  123. {
  124.     /* intermediate terms to speed up loop */
  125.     long t1 = rx*rx, t2 = t1<<1, t3 = t2<<1;
  126.     long t4 = ry*ry, t5 = t4<<1, t6 = t5<<1;
  127.     long t7 = rx*t5, t8 = t7<<1, t9 = 0L;
  128.     long d1 = t2 - t7 + (t4>>1);    /* error terms */
  129.     long d2 = (t1>>1) - t8 + t5;
  130.  
  131.     register int x = rx, y = 0;    /* ellipse points */
  132.  
  133.     while (d2 < 0)            /* til slope = -1 */
  134.     {
  135.         /* draw 4 points using symmetry */
  136.             pr_put (pr, center_x + x, center_y + y, 1);
  137.             pr_put (pr, center_x + x, center_y - y, 1);
  138.             pr_put (pr, center_x - x, center_y + y, 1);
  139.             pr_put (pr, center_x - x, center_y - y, 1);
  140.  
  141.         y++;        /* always move up here */
  142.         t9 += t3;    
  143.         if (d1 < 0)    /* move straight up */
  144.         {
  145.             d1 += t9 + t2;
  146.             d2 += t9;
  147.         }
  148.         else        /* move up and left */
  149.         {
  150.             x--;
  151.             t8 -= t6;
  152.             d1 += t9 + t2 - t8;
  153.             d2 += t9 + t5 - t8;
  154.         }
  155.     }
  156.  
  157.     do                 /* rest of top right quadrant */
  158.     {
  159.         /* draw 4 points using symmetry */
  160.             pr_put (pr, center_x + x, center_y + y, 1);
  161.             pr_put (pr, center_x + x, center_y - y, 1);
  162.             pr_put (pr, center_x - x, center_y + y, 1);
  163.             pr_put (pr, center_x - x, center_y - y, 1);
  164.  
  165.         x--;        /* always move left here */
  166.         t8 -= t6;    
  167.         if (d2 < 0)    /* move up and left */
  168.         {
  169.             y++;
  170.             t9 += t3;
  171.             d2 += t9 + t5 - t8;
  172.         }
  173.         else        /* move straight left */
  174.             d2 += t5 - t8;
  175.     } while (x>=0);
  176. }
  177.  
  178.  
  179. static fill_ellipse (pr, center_x, center_y, rx, ry)
  180. struct pixrect *pr;
  181. int    center_x, center_y;
  182. int    rx, ry;
  183. {
  184.     long t1 = rx*rx, t2 = t1<<1, t3 = t2<<1;
  185.     long t4 = ry*ry, t5 = t4<<1, t6 = t5<<1;
  186.     long t7 = rx*t5, t8 = t7<<1, t9 = 0;
  187.     long d1 = t2 - t7 + (t4>>1);    /* error terms */
  188.     long d2 = (t1>>1) - t8 + t5;
  189.     register int x = rx, y = 0;    /* ellipse points */
  190.         register int t;            /* used in fill operation */
  191.     int wid;            /* width of fill */
  192.  
  193.     while (d2 < 0)            /* til slope = -1 */
  194.     {
  195.          /* fill in leftward to inner ellipse */
  196.             for (t=x; (!pr_get(pr, center_x+t, center_y+y)) && t; t--);
  197.         wid = x - t + 1;
  198.         pr_rop (pr, center_x+t, center_y+y, wid, 1,
  199.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  200.         pr_rop (pr, center_x-x, center_y+y, wid, 1,
  201.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  202.         pr_rop (pr, center_x+t, center_y-y, wid, 1,
  203.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  204.         pr_rop (pr, center_x-x, center_y-y, wid, 1,
  205.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  206.  
  207.         y++;        /* always move up here */
  208.         t9 += t3;    
  209.         if (d1 < 0)    /* move straight up */
  210.         {
  211.             d1 += t9 + t2;
  212.             d2 += t9;
  213.         }
  214.         else        /* move up and left */
  215.         {
  216.             x--;
  217.             t8 -= t6;
  218.             d1 += t9 + t2 - t8;
  219.             d2 += t9 + t5 - t8;
  220.         }
  221.     }
  222.  
  223.     do                 /* rest of top right quadrant */
  224.     {
  225.         /* fill in downward to inner ellipse */
  226.             for (t=y; (!pr_get(pr, center_x+x, center_y+t)) && t; t--);
  227.         wid = y - t + 1;
  228.         pr_rop (pr, center_x+x, center_y+t, 1, wid,
  229.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  230.         pr_rop (pr, center_x+x, center_y-y, 1, wid,
  231.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  232.         pr_rop (pr, center_x-x, center_y+t, 1, wid,
  233.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  234.         pr_rop (pr, center_x-x, center_y-y, 1, wid,
  235.             PIX_SET | PIX_DONTCLIP, NULL, 0, 0);
  236.  
  237.         x--;        /* always move left here */
  238.         t8 -= t6;    
  239.         if (d2 < 0)    /* move up and left */
  240.         {
  241.             y++;
  242.             t9 += t3;
  243.             d2 += t9 + t5 - t8;
  244.         }
  245.         else        /* move straight left */
  246.         {
  247.             d2 += t5 - t8;
  248.         }
  249.     } while (x>=0);
  250. }
  251. -- 
  252. Jack C. Morrison    Jet Propulsion Laboratory
  253. (818)354-1463        jackm@jpl-devvax.jpl.nasa.gov
  254. "The paycheck is part government property, but the opinions are all mine."
  255.  
  256.  
  257.